#include "picture_gui.h"
#include "lvgl/lvgl.h"
#include <stdlib.h>
#include <stdio.h>

LV_IMG_DECLARE(butterfly)

LV_FONT_DECLARE(lv_font_mh_22)
LV_FONT_DECLARE(lv_font_mh_24)

#define COLUMN_NUM (sizeof(col_dsc) / sizeof(col_dsc[0]) - 1)
#define ROW_NUM (sizeof(row_dsc) / sizeof(row_dsc[0]) - 1)

#define TITLE_HEIGHT 40

struct title
{
    lv_obj_t *cont;
    lv_obj_t *label;
    lv_obj_t *prev_btn;
    lv_obj_t *next_btn;
};

static void picture_gui_grid_dsc_init(void);
static lv_img_dsc_t *create_img_dsc(ImgInfo info);
static lv_obj_t *picture_gui_create_img(int x, int y, ImgInfo info);
static void drag_event_handler(lv_event_t *e);
static void img_list_click_event_handler(lv_event_t *e);
static void img_click_event_handler(lv_event_t *e);
static void title_btn_click_event_handler(lv_event_t *e);
static void img_anim_ready_handler(lv_anim_t *anim);
static void img_del(lv_obj_t *img);
static uint8_t *rgb888_to_argb888(const uint8_t *src, int len);

// gui回调函数集
static gui_opt_t gui_opts;

// LCD分辨率
static uint32_t lcd_w = 480;
static uint32_t lcd_h = 272;

// 图片界面容器
static lv_obj_t *cont = NULL;

// 背景图片
static lv_obj_t *back_img = NULL;

// 上方标题栏
static struct title title;

// 退出按钮
static lv_obj_t *exit_btn = NULL;

// 保存上一张图片对象
static lv_obj_t *opened_img = NULL;

// 保存上一张图片tag
static int opened_tag = 0;

// 网格布局列cell
static lv_coord_t col_dsc[4 + 1] = {0};

// 网格布局行cell
static lv_coord_t row_dsc[6 + 1] = {0};

// 网格布局cell行索引
static lv_coord_t row_index = 0;

// 网格布局cell列索引
static lv_coord_t col_index = 0;

// 图片列表当前活动页索引
static int active_page = 1;

//图片列表总页数
static int total_page = 1;
/*
 *@brief 初始化picture界面
 */
void picture_gui_init(gui_opt_t *opts)
{
    lv_obj_t *act = lv_scr_act();

    if (opts != NULL) // 设置回调函数集合
        memcpy(&gui_opts, opts, sizeof(gui_opt_t));

    // 获取显示设备分辨率
    lcd_w = lv_disp_get_hor_res(NULL);
    lcd_h = lv_disp_get_ver_res(NULL);

    // 初始化网格布局
    picture_gui_grid_dsc_init();

    // 创建背景图片
    back_img = lv_img_create(act);
    lv_obj_clear_flag(back_img, LV_OBJ_FLAG_SCROLLABLE);
    lv_img_set_src(back_img, "S:./res/background/picturebg.bin");

    // 创建标题栏
    title.cont = lv_obj_create(back_img);
    lv_obj_set_size(title.cont, lcd_w, TITLE_HEIGHT);
    lv_obj_set_style_radius(title.cont, 0, LV_STATE_DEFAULT);
    lv_obj_set_style_border_width(title.cont, 0, LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(title.cont, lv_color_black(), LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(title.cont, LV_OPA_70, LV_STATE_DEFAULT);
    lv_obj_clear_flag(title.cont, LV_OBJ_FLAG_SCROLLABLE);      //禁用滚动

    title.label = lv_label_create(title.cont);
    lv_obj_set_height(title.label, TITLE_HEIGHT);
    lv_label_set_text(title.label, "图片(0/0)");
    lv_obj_set_style_text_color(title.label, lv_color_white(), LV_STATE_DEFAULT);
    lv_obj_set_style_text_font(title.label, &lv_font_mh_24, LV_STATE_DEFAULT);
    lv_obj_set_style_text_opa(title.label, LV_OPA_80, LV_STATE_DEFAULT);
    lv_obj_center(title.label);

    for(int i = 0; i < 2; i++)
    {
        lv_obj_t *btn = lv_btn_create(title.cont);
        const char *string;

        if(i == 0)
        {
            title.prev_btn = btn;
            string = "上一页";
        }
        else
        {
            title.next_btn = btn;
            string = "下一页";
        }
        lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE);       //设置无法触摸
        lv_obj_add_flag(btn, LV_OBJ_FLAG_HIDDEN);       //隐藏按钮
        lv_obj_set_size(btn, 100, TITLE_HEIGHT - 4);
        lv_obj_add_event_cb(btn, title_btn_click_event_handler, LV_EVENT_CLICKED, NULL);
        lv_obj_t *label = lv_label_create(btn);
        lv_label_set_text(label, string);
        lv_obj_set_style_text_color(label, lv_color_white(), LV_STATE_DEFAULT);
        lv_obj_set_style_text_font(label, &lv_font_mh_22, LV_STATE_DEFAULT);
        lv_obj_set_style_text_opa(label, LV_OPA_80, LV_STATE_DEFAULT);
        lv_obj_center(label);
        
    }

    lv_obj_align(title.prev_btn, LV_ALIGN_LEFT_MID, 10, 0);
    lv_obj_align(title.next_btn, LV_ALIGN_RIGHT_MID, -10, 0);

    // 创建背景容器
    cont = lv_obj_create(back_img);
    lv_obj_set_size(cont, lcd_w, lcd_h - TITLE_HEIGHT);
    lv_obj_align_to(cont, title.cont, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
    lv_obj_set_grid_dsc_array(cont, col_dsc, row_dsc);
    lv_obj_set_layout(cont, LV_LAYOUT_GRID);
    lv_obj_set_style_pad_all(cont, 8, LV_STATE_DEFAULT);                // 设置网格cell四周填充宽度
    lv_obj_set_style_outline_width(cont, 0, LV_STATE_DEFAULT);          // 设置网格cell四周外部线条宽度
    lv_obj_set_style_border_opa(cont, LV_OPA_TRANSP, LV_STATE_DEFAULT); // 设置边框透明
    lv_obj_set_style_bg_opa(cont, LV_OPA_TRANSP, LV_STATE_DEFAULT);     // 设置背景透明

    //创建退出按钮
    exit_btn = lv_obj_create(back_img);
    lv_obj_set_size(exit_btn, 70, 70);
    lv_obj_set_pos(exit_btn, 935, 267);
    lv_obj_clear_flag(exit_btn, LV_OBJ_FLAG_SCROLLABLE);            //禁止滚动
    lv_obj_set_style_radius(exit_btn, 35, LV_STATE_DEFAULT);
    lv_obj_set_style_bg_color(exit_btn, lv_color_hex(0xffffff), LV_STATE_DEFAULT);
    lv_obj_set_style_border_opa(exit_btn, LV_OPA_TRANSP, LV_STATE_DEFAULT);     //A边框透明
    lv_obj_set_style_bg_opa(exit_btn, LV_OPA_50, LV_STATE_DEFAULT);
    lv_obj_set_style_bg_opa(exit_btn, LV_OPA_90, LV_STATE_PRESSED);

    lv_obj_t *img = lv_img_create(exit_btn);
    lv_img_set_src(img, &butterfly);
    lv_obj_align(img, LV_ALIGN_CENTER, 0, 0);
    lv_obj_add_flag(img, LV_OBJ_FLAG_EVENT_BUBBLE);

    lv_obj_add_event_cb(exit_btn, drag_event_handler, LV_EVENT_PRESSING, NULL);
    if (gui_opts.exit_cb != NULL)
        lv_obj_add_event_cb(exit_btn, gui_opts.exit_cb, LV_EVENT_SHORT_CLICKED, NULL);
}

/*
 *@brief  设置图片页数
 *@param total 图片总数
 */
void picture_gui_set_img_list_page(int total)
{
    total_page = total / (24 + 1) + 1;

    lv_label_set_text_fmt(title.label, "Picture(%d/%d)", active_page, total_page);

    if(total_page > 1)
    {
        lv_obj_clear_flag(title.prev_btn, LV_OBJ_FLAG_HIDDEN);       //显示按钮
        lv_obj_clear_flag(title.next_btn, LV_OBJ_FLAG_HIDDEN);       //显示按钮
    }
}   

/*
 *@brief 在图片列表添加一个img对象显示图片缩略图
 *@param info 图片信息
 *@param tag 图片标签
 *@param get_image 获取图像原始数据回调
 */
const uint8_t *picture_gui_list_add_img(ImgInfo info, int tag)
{
    lv_img_dsc_t *src = create_img_dsc(info);

    ImgData *data = (ImgData *)malloc(sizeof(ImgData));

    data->src = src;
    data->tag = tag;

    if (src != NULL)
    {
        lv_obj_t *cell = lv_img_create(cont);
        lv_obj_set_grid_cell(cell, LV_GRID_ALIGN_STRETCH, col_index, 1, LV_GRID_ALIGN_STRETCH, row_index, 1);
        lv_obj_set_style_bg_color(cell, lv_color_black(), LV_STATE_DEFAULT);
        lv_obj_set_style_outline_width(cell, 2, LV_STATE_FOCUSED);
        lv_obj_set_style_outline_color(cell, lv_color_hex(0xffff00ff), LV_STATE_FOCUSED);
        lv_obj_set_style_outline_pad(cell, 6, LV_STATE_FOCUSED);
        lv_obj_add_flag(cell, LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_CLICKABLE);

        lv_obj_t *img = lv_img_create(cell);
        lv_img_set_src(img, src);
        lv_obj_add_flag(img, LV_OBJ_FLAG_EVENT_BUBBLE |
                                 LV_OBJ_FLAG_CLICK_FOCUSABLE |
                                 LV_OBJ_FLAG_CLICKABLE); // 设置事件同时传播到父对象cell
        lv_obj_center(img);

        lv_obj_set_user_data(img, data);
        lv_obj_add_event_cb(img, img_list_click_event_handler, LV_EVENT_SHORT_CLICKED, NULL);

        if (++col_index == COLUMN_NUM)
        {
            col_index = 0;
            row_index++;
        }
    }

    return src->data;
}

/*
 *@brief 清空图片列表
 */
void picture_gui_list_clear(void)
{
    lv_obj_t *cell = NULL;

    do
    {
        cell = lv_obj_get_child(cont, -1);
        if (cell != NULL)
        {
            lv_obj_t *img = lv_obj_get_child(cell, -1);
            if (img != NULL)
            {
                ImgData *data = lv_obj_get_user_data(img); // 释放图像数据
                free((void *)data->src->data);
                free((void *)data->src);
                free((void *)data);
            }

            lv_obj_del(cell);
        }
    } while (cell != NULL);

    col_index = 0;          //清除行列索引
    row_index = 0;
}

/*
 *@brief 切换图片显示
 *@param tag 切换的图片的tag
 *@param dir 切换的方向，true-正序，false-逆序
 */
void picture_gui_change_img(int tag, bool dir)
{
    if (gui_opts.get_image != NULL)
    {
        ImgInfo imginfo;
        gui_opts.get_image(tag, &imginfo);

        printf("img create, tag:%d\n", tag);

        int start_x = dir ? lcd_w : -lcd_w;

        lv_obj_t *img = picture_gui_create_img(start_x, 0, imginfo);
        if (img != NULL)
        {
            // 添加动画，删除上一个图片对象及数据
            lv_anim_t anim;

            lv_anim_init(&anim);
            lv_anim_set_var(&anim, img);
            lv_anim_set_values(&anim, start_x, 0);
            lv_anim_set_time(&anim, 500);
            lv_anim_set_exec_cb(&anim, (lv_anim_exec_xcb_t)lv_obj_set_x);
            lv_anim_set_path_cb(&anim, lv_anim_path_ease_out); // 动画轨迹：最后变慢
            lv_anim_set_ready_cb(&anim, img_anim_ready_handler);
            lv_anim_set_user_data(&anim, opened_img);
            lv_anim_start(&anim); // 开启动画

            opened_img = img; // 保存图片对象
            opened_tag = tag; // 保存图片tag
        }
    }
}

/*
 *@brief 完成列表页面切换完成调用函数
 */
void picture_gui_set_list_change_over(void)
{
    lv_obj_add_flag(title.prev_btn, LV_OBJ_FLAG_CLICKABLE);       //设置按钮可触摸
    lv_obj_add_flag(title.next_btn, LV_OBJ_FLAG_CLICKABLE);
}

/*
 *@brief 清空picture界面
 */
void picture_gui_release()
{
    picture_gui_list_clear();       //清空图片列表

    lv_obj_del(back_img);
}

/*
 *@brief 在指定位置创建一个img
 *@param w 图片宽度(像素)
 *@param h 图片高度(像素)
 *@param img 创建的img对象
 */
static lv_obj_t *picture_gui_create_img(int x, int y, ImgInfo info)
{
    lv_img_dsc_t *src = create_img_dsc(info);
    lv_obj_t *img = NULL;

    if (src != NULL)
    {
        img = lv_img_create(back_img);
        lv_obj_set_pos(img, x, y);
        lv_img_set_src(img, src);
        lv_obj_center(img);

        lv_obj_set_user_data(img, src);
    }

    return img;
}

/*
 *@brief 根据图像数据构建一个img_dsc
 *@param w 图片宽度(像素)
 *@param h 图片高度(像素)
 *@param img_map 图像数据
 */
static lv_img_dsc_t *create_img_dsc(ImgInfo info)
{
    lv_img_dsc_t *src = NULL;
    const uint8_t *map = info.img_map;

    src = (lv_img_dsc_t *)malloc(sizeof(lv_img_dsc_t));
    memset(src, 0, sizeof(lv_img_dsc_t));

    if (src != NULL)
    {
        if (info.bpp == 24)
        {
            map = rgb888_to_argb888(info.img_map, info.w * info.h);
            free((void *)info.img_map);
        }
        src->header.always_zero = 0;
        src->header.w = info.w;
        src->header.h = info.h;
        src->data_size = info.w * info.h * LV_COLOR_SIZE / 8;
        src->header.cf = LV_IMG_CF_TRUE_COLOR;
        src->data = map;
    }

    return src;
}

/*
 *@brief 初始化picture界面网格布局cell
 */
static void picture_gui_grid_dsc_init()
{
    int i;

    for (i = 0; i < COLUMN_NUM; i++)
        col_dsc[i] = CELL_W;
    col_dsc[i] = LV_GRID_TEMPLATE_LAST;

    for (i = 0; i < ROW_NUM; i++)
        row_dsc[i] = CELL_H;
    row_dsc[i] = LV_GRID_TEMPLATE_LAST;
}

/*
 *@brief 长按拖动控件事件函数
 */
static void drag_event_handler(lv_event_t *e)
{
    lv_obj_t *obj = lv_event_get_target(e);

    lv_indev_t *indev = lv_indev_get_act();
    if (indev == NULL)
        return;

    lv_point_t vect;
    lv_indev_get_vect(indev, &vect);

    lv_coord_t x = lv_obj_get_x(obj) + vect.x;
    lv_coord_t y = lv_obj_get_y(obj) + vect.y;
    lv_obj_set_pos(obj, x, y);
}

/*
 *@brief 图片列表图标点击事件函数
 */
static void img_list_click_event_handler(lv_event_t *e)
{
    lv_obj_t *img = lv_event_get_target(e);

    ImgData *data = lv_obj_get_user_data(img);

    if (data != NULL)
    {
        picture_gui_change_img(data->tag, true); // 创建图片
    }
}

/*
 *@brief 图片单击事件函数
 */
static void img_click_event_handler(lv_event_t *e)
{
    lv_obj_t *img = lv_event_get_target(e);
    lv_indev_t *indev = lv_indev_get_act();

    if (indev == NULL)
        return;

    lv_point_t point;
    lv_indev_get_point(indev, &point); // 获取触摸坐标

    if (point.x < lcd_w / 4) // 切换上一张
    {
        if (gui_opts.get_prev_tag != NULL)
        {
            int tag = gui_opts.get_prev_tag(opened_tag);
            picture_gui_change_img(tag, false); // 创建图片
        }
    }
    else if (point.x < lcd_w * 3 / 4) // 删除图片对象
    {
        img_del(img);

        opened_tag = 0;
        opened_img = NULL;
    }
    else if (point.x < lcd_w) // 切换下一张
    {
        if (gui_opts.get_next_tag != NULL)
        {
            int tag = gui_opts.get_next_tag(opened_tag);
            picture_gui_change_img(tag, true); // 创建图片
        }
    }
}

/*
 *@brief 标题栏按钮点击事件回调函数
 */
static void title_btn_click_event_handler(lv_event_t *e)
{
    lv_obj_t *btn = lv_event_get_target(e);

    picture_gui_list_clear();

    if(btn == title.prev_btn)
        active_page = active_page > 1 ? active_page - 1 :  total_page;
    else if(btn == title.next_btn)
        active_page = active_page < total_page ? active_page + 1 :  1;

    lv_label_set_text_fmt(title.label, "图片(%d/%d)", active_page, total_page);

    lv_obj_clear_flag(title.prev_btn, LV_OBJ_FLAG_CLICKABLE);       //设置无法触摸
    lv_obj_clear_flag(title.next_btn, LV_OBJ_FLAG_CLICKABLE);

    if(gui_opts.change_list_page != NULL)
        gui_opts.change_list_page(active_page);
}

/*
 *@brief 图片动画结束回调函数
 */
static void img_anim_ready_handler(lv_anim_t *anim)
{
    lv_obj_t *old_img = lv_anim_get_user_data(anim);

    if (old_img != NULL)
        img_del(old_img);

    lv_obj_t *img = anim->var;

    lv_obj_add_flag(img, LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_CLICKABLE); // 设置可触摸
    lv_obj_add_event_cb(img, img_click_event_handler, LV_EVENT_SHORT_CLICKED, NULL);
}

/*
 *@brief 删除img对象及其图像数据
 */
static void img_del(lv_obj_t *img)
{
    if (img == NULL)
        return;

    lv_img_dsc_t *src = lv_obj_get_user_data(img);
    if (src != NULL)
    {
        free((void *)src->data);
        free((void *)src);
    }

    lv_obj_del_async(img);
}

static uint8_t *rgb888_to_argb888(const uint8_t *src, int len)
{
    uint8_t *argb888 = malloc(len * 4);

    for (int i = 0; i < len; i++)
    {
        argb888[4 * i] = src[3 * i];
        argb888[4 * i + 1] = src[3 * i + 1];
        argb888[4 * i + 2] = src[3 * i + 2];
        argb888[4 * i + 3] = 0xff;
    }

    return argb888;
}